/**
 * 
 */
package pers.xwx.demo.service;

import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Date;
import java.util.List;
import java.util.UUID;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.aliyun.oss.HttpMethod;
import com.aliyun.oss.OSSClient;
import com.aliyun.oss.common.auth.ServiceSignature;
import com.aliyun.oss.common.comm.RequestMessage;
import com.aliyun.oss.common.utils.DateUtil;
import com.aliyun.oss.internal.OSSHeaders;
import com.aliyun.oss.internal.OSSUtils;
import com.aliyun.oss.internal.SignUtils;
import com.aliyun.oss.model.CompleteMultipartUploadRequest;
import com.aliyun.oss.model.CompleteMultipartUploadResult;
import com.aliyun.oss.model.GenericRequest;
import com.aliyun.oss.model.InitiateMultipartUploadRequest;
import com.aliyun.oss.model.InitiateMultipartUploadResult;
import com.aliyun.oss.model.PartETag;
import com.aliyun.oss.model.UploadPartRequest;
import com.aliyun.oss.model.UploadPartResult;
import com.google.common.collect.Lists;
import com.google.common.io.Files;

import pers.xwx.demo.dto.RequestCompleteUploadDTO;
import pers.xwx.demo.dto.RequestMultipartUploadDataDTO;
import pers.xwx.demo.dto.RequestPartETagDTO;
import pers.xwx.demo.dto.ResultMultipartUploadDTO;
import pers.xwx.demo.dto.ResultPartETagDTO;
import pers.xwx.demo.dto.ResultUploadInfoDTO;
import pers.xwx.demo.property.OSSProperties;

/**
 * @author user
 *
 */
@Service
public class OSSServiceImpl implements IOSSService {

	/**
	 * inject oss client
	 */
	@Autowired
	private OSSClient ossClient;

	/**
	 * inject oss properties
	 */
	@Autowired
	private OSSProperties ossProps;

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * pers.xwx.demo.service.IOSSService#getDownloadSignatureUrl(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public String getDownloadSignatureUrl(String bucketName, String objectKey) {
		long expiredTime = System.currentTimeMillis() + ossProps.getDownloadExpireTime();
		Date expiredDate = new Date(expiredTime);
		String signature = ossClient.generatePresignedUrl(bucketName, objectKey, expiredDate).toString();

		return signature;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pers.xwx.demo.service.IOSSService#getUploadSignature(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public ResultUploadInfoDTO getUploadSignature(String bucketName, String fileName) {
		// 创建对象
		ResultUploadInfoDTO result = new ResultUploadInfoDTO();
		// 时间信息
		String date = DateUtil.formatRfc822Date(new Date());
		result.setDate(date);
		// 生成object_name
		String fileExt = Files.getFileExtension(fileName);
		String uuid = UUID.randomUUID().toString().replaceAll("-", "");
		StringBuilder sb = new StringBuilder(uuid);
		sb.append(".");
		sb.append(fileExt);
		String objectName = sb.toString();
		result.setObjectName(objectName);
		// 放入文件名
		result.setFileName(fileName);
		// disposition
		try {
			result.setDispositionValue("attachment;filename=" + URLEncoder.encode(fileName, "UTF-8"));
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 放入bucket
		result.setBucketName(bucketName);
		// 生成签名
		GenericRequest request = new GenericRequest(bucketName, objectName);
		RequestMessage requestSign = new RequestMessage(request);
		requestSign.addHeader(OSSHeaders.DATE, date);
		requestSign.addHeader(OSSHeaders.CONTENT_TYPE, "application/octet-stream");
		result.setSignature(this.generateSignature(requestSign, bucketName, objectName));

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pers.xwx.demo.service.IOSSService#initMultipartUpload(java.lang.String,
	 * java.lang.String)
	 */
	@Override
	public ResultMultipartUploadDTO initMultipartUpload(String bucketName, String fileName) {
		// 创建对象
		ResultMultipartUploadDTO result = new ResultMultipartUploadDTO();
		// 生成objectKey
		String fileNameNoExt = Files.getNameWithoutExtension(fileName);
		String fileExt = Files.getFileExtension(fileName);
		StringBuilder sb = new StringBuilder(fileNameNoExt);
		sb.append("_");
		sb.append(String.valueOf(System.currentTimeMillis()));
		sb.append(".");
		sb.append(fileExt);
		String objectName = sb.toString();
		result.setFileName(fileName);
		result.setObjectName(objectName);
		result.setBucketName(bucketName);
		// 初始化分片上传
		InitiateMultipartUploadRequest request = new InitiateMultipartUploadRequest(bucketName, objectName);
		try {
			String dispositionValue = "attachment;filename=" + URLEncoder.encode(fileName, "UTF-8");
			request.addHeader("Content-Disposition", dispositionValue);
			// oss 分片上传出事化
			InitiateMultipartUploadResult initResult = ossClient.initiateMultipartUpload(request);
			result.setUploadId(initResult.getUploadId());

			return result;
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see pers.xwx.demo.service.IOSSService#dataMultipartUpload(pers.xwx.demo.dto.
	 * RequestMultipartUploadDataDTO)
	 */
	@Override
	public ResultPartETagDTO dataMultipartUpload(RequestMultipartUploadDataDTO data) {
		// 返回对象
		ResultPartETagDTO result = new ResultPartETagDTO();
		// 分片上传文件流
		UploadPartRequest request = new UploadPartRequest();
		request.setKey(data.getObjectName());
		request.setBucketName(data.getBucketName());
		try {
			request.setInputStream(data.getFile().getInputStream());
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		request.setUploadId(data.getUploadId());
		request.setPartNumber(data.getPartNum());
		UploadPartResult resultTmp = ossClient.uploadPart(request);

		result.setPartNum(resultTmp.getPartNumber());
		result.setPartEtag(resultTmp.getETag());

		return result;
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * pers.xwx.demo.service.IOSSService#getMultipleUploadComplete(pers.xwx.demo.dto
	 * .RequestCompleteUploadDTO)
	 */
	@Override
	public CompleteMultipartUploadResult getMultipleUploadComplete(RequestCompleteUploadDTO data) {
		// partEtag生成
		List<PartETag> partEtags = Lists.newArrayList();
		for (RequestPartETagDTO entity : data.getPartETags()) {
			partEtags.add(new PartETag(entity.getPartNumber(), entity.getPartTag()));
		}
		// uploadId不为空，调用分片完成接口
		CompleteMultipartUploadRequest request = new CompleteMultipartUploadRequest(data.getOssBucketName(),
				data.getOssObjectName(), data.getUploadId(), partEtags);
		CompleteMultipartUploadResult result = ossClient.completeMultipartUpload(request);

		return result;
	}

	/**
	 * 生成签名
	 * 
	 * @param requestSign
	 * @param objectName
	 * @return
	 */
	private String generateSignature(RequestMessage requestSign, String bucketName, String objectName) {
		String resourcePath = "/" + ((bucketName != null) ? bucketName + "/" : "")
				+ ((objectName != null ? objectName : ""));
		String canonicalString = SignUtils.buildCanonicalString(HttpMethod.PUT.toString(), resourcePath, requestSign,
				null);
		String signature = ServiceSignature.create().computeSignature(
				ossClient.getCredentialsProvider().getCredentials().getSecretAccessKey(), canonicalString);
		return OSSUtils.composeRequestAuthorization(
				ossClient.getCredentialsProvider().getCredentials().getAccessKeyId(), signature);
	}

}
